<!DOCTYPE html>
<html lang="en">

<head>
	<title>医疗三维分析</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<link rel="stylesheet" href="css/switch.css" />

	<style>
		body {
			font-family: Monospace;
			background-color: #000;
			color: #fff;
			margin: 0px;
			overflow: hidden;
		}

		#info {
			color: #fff;
			position: absolute;
			top: 10px;
			width: 100%;
			text-align: center;
			display: block;
		}

		#info a {
			color: #046;
			font-weight: bold;
		}
	</style>
</head>

<body>
	<div id="info">
		<div style="position: absolute;line-height: 20px; width: 70px;height: 20px; top: 10px; right: 10px;background-color: rgb(0, 162, 255);"
			onclick="ClickCj()">拆解</div>
		<div style="position: absolute;line-height: 20px; width: 70px; height: 20px; top: 50px; right: 10px;background-color: rgb(0, 162, 255);"
			onclick="ClickPq()">剖切</div>

		<input type="range" min="-100" max="100" value="0" class="slider" id="myRange"
			style="position: absolute; top: 10px;right: 120px; width: 120px" hidden>

		</input>

		<input type="range" min="-15" max="15" value="0" class="slider" id="myPouqie"
			style="position: absolute; top: 50px;right: 120px; width: 120px" hidden	>
		</input>

		<div id="promote" style="position: absolute;"></div>

	</div>

	<script>
		function ClickCj() {
			document.getElementById('myRange').hidden = false;
			document.getElementById('myPouqie').hidden = true;
			helpers.visible = false;
			ResetPos();
			render();

		}
		function ClickPq() {
			document.getElementById('myRange').hidden = true;
			document.getElementById('myPouqie').hidden = false;

			helpers.visible = true;
			ResetPos();
			render();
		}

		function ResetPos() {
			for (var i = 0; i < group.children.length; i++) {
				group.children[i].traverse(function (value) {
					if (!value.isMesh || !value.worldDir) return;

					//爆炸公式
					value.position.copy(new THREE.Vector3().copy(value.userData.oldPs).add(new THREE.Vector3().copy(value.worldDir).multiplyScalar(0)))
				});
			}
			document.getElementById('myRange').value = 0;
			document.getElementById('myPouqie').value = 0;

			for (var j = 0; j < clipPlanes.length; j++) {

				clipPlanes[j].constant = 15;

			}
		}
	</script>
	<!-- 添加列表生成器 -->
	<script>

		function addList(arrs) {
			var maindiv = document.createElement("div");
			maindiv.id = "parent";
			maindiv.style = "position:absolute;right: 40px;top: 100px;"
			document.body.appendChild(maindiv);

			for (i = 0; i < arrs.length; i++) {
				var objdiv = document.createElement("div");
				objdiv.className = "switch-container";
				maindiv.appendChild(objdiv);

				var objdiv2 = document.createElement("input");
				objdiv2.className = "switch";
				objdiv2.id = "switch" + i;
				objdiv2.type = "checkbox";
				objdiv2.checked = true;
				objdiv.appendChild(objdiv2);

				var objdiv3 = document.createElement("label");
				objdiv3.setAttribute("for", objdiv2.id);
				objdiv3.id = i;
				objdiv3.addEventListener('click', function (e) {
					selectedMesh(
					document.getElementById('switch' + this.id).checked,
					document.getElementById('name' + this.id).innerText);
				});
				objdiv.appendChild(objdiv3);

				var objdiv4 = document.createElement("div");
				objdiv4.id="name"+i;
				objdiv4.className = "textClass";
				objdiv4.innerText = arrs[i];
				objdiv.appendChild(objdiv4);

			}
			function selectedMesh(ishidden,name)
			{
				for(var i = 0; i < group.children.length; i ++)
				{
					if(group.children[i].name == name)
					{
						group.children[i].visible = ishidden ? false :true;
						return;
					}
				}
			}
		}


	</script>

	<script src="build/three.js"></script>
	<script src="js/controls/OrbitControls.js"></script>
	<script src="js/loaders/STLLoader.js"></script>


	<script src="js/shaders/CopyShader.js"></script>
	<script src="js/shaders/FXAAShader.js"></script>
	<script src="js/postprocessing/EffectComposer.js"></script>
	<script src="js/postprocessing/RenderPass.js"></script>
	<script src="js/postprocessing/ShaderPass.js"></script>
	<script src="js/postprocessing/OutlinePass.js"></script>


	<script>

		//模型包围盒
		var modelBox3 = new THREE.Box3();

		var meshBox3 = new THREE.Box3();

		var scene, camera, renderer, exporter, mesh;
		let selectedObject = null;
		const pointer = new THREE.Vector2();
		const raycaster = new THREE.Raycaster();
		const group = new THREE.Group();

		var mouse = new THREE.Vector2();
		var selectedObjects = [];
		var composer, effectFXAA, outlinePass;
		var helpers;

		var params = {
			clipIntersection: true,
			planeConstant: 0,
			showHelpers: false
		};

		var clipPlanes = [
			new THREE.Plane(new THREE.Vector3(1, 0, 0), 0),
			new THREE.Plane(new THREE.Vector3(0, - 1, 0), 0),
			new THREE.Plane(new THREE.Vector3(0, 0, - 1), 0)
		];


		init();
		animate();

		function init() {

			//加载renderer

			renderer = new THREE.WebGLRenderer({ antialias: true });
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(window.innerWidth, window.innerHeight);
			renderer.shadowMap.enabled = true;
			renderer.localClippingEnabled = true;
			document.body.appendChild(renderer.domElement);

			scene = new THREE.Scene();

			camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 200);
			camera.position.set(0, 30, 45);

			var controls = new THREE.OrbitControls(camera, renderer.domElement);
			// controls.target.set(100, 100, 100);
			controls.addEventListener('change', render);
			controls.minDistance = 10;
			controls.maxDistance = 100;

			// scene.background = new THREE.Color(0xa0a0a0);

			var light = new THREE.HemisphereLight(0xffffff, 0x080808, 1);
			scene.add(light);
			scene.add(new THREE.AmbientLight(0x505050));

			//加载stl模型
			var loader = new THREE.STLLoader();
			var nameArr = ['髌骨', '腓骨', '股骨', '胫骨', '皮肤'];
			for (let i = 1; i < nameArr.length + 1; i++) {
				loader.load('stl/' + i + '.stl', function (geometry) {
					var mat = new THREE.MeshLambertMaterial({
						color: new THREE.Color().setHSL(Math.random(), 0.5, 0.5),
						side: THREE.DoubleSide,
						clippingPlanes: clipPlanes,
						clipIntersection: params.clipIntersection
					});
					var mesh = new THREE.Mesh(geometry, mat);
					mesh.name = nameArr[i - 1];
					mesh.castShadow = true;
					mesh.position.set(-10, 10, -10);
					// mesh.rotation.x = -0.5 * Math.PI; //将模型摆正
					mesh.scale.set(0.1, 0.1, 0.1); //缩放
					// geometry.center(); //居中显示
					group.add(mesh);

					//获取模型的包围盒
					modelBox3.expandByObject(mesh);

					//计算模型的中心点坐标，这个为爆炸中心
					var modelWorldPs = new THREE.Vector3().addVectors(modelBox3.max, modelBox3.min).multiplyScalar(0.5);

					mesh.traverse(function (value) {
						if (value.isMesh) {
							meshBox3.setFromObject(value);

							//获取每个mesh的中心点，爆炸方向为爆炸中心点指向mesh中心点
							var worldPs = new THREE.Vector3().addVectors(meshBox3.max, meshBox3.min).multiplyScalar(0.5);
							if (isNaN(worldPs.x)) return;
							//计算爆炸方向
							value.worldDir = new THREE.Vector3().subVectors(worldPs, modelWorldPs).normalize();
							//保存初始坐标
							value.userData.oldPs = value.getWorldPosition(new THREE.Vector3())
						}
					});

					function applyScalar(scalar) {

						mesh.traverse(function (value) {
							if (!value.isMesh || !value.worldDir) return;

							//爆炸公式
							value.position.copy(new THREE.Vector3().copy(value.userData.oldPs).add(new THREE.Vector3().copy(value.worldDir).multiplyScalar(scalar)))
						});

					}

					document.querySelector("#myRange").addEventListener('input', function (evt) {
						applyScalar(this.value * 0.2)
					})

					document.querySelector("#myPouqie").addEventListener('input', function (evt) {
						for (var j = 0; j < clipPlanes.length; j++) {

							clipPlanes[j].constant = this.value;

						}

						render();
					})
				});
			}
			//添加列表数据
			addList(nameArr);
			scene.add(group);
			// helpers
			helpers = new THREE.Group();
			helpers.add(new THREE.AxesHelper(500000));
			helpers.add(new THREE.PlaneHelper(clipPlanes[0], 30, 0xff0000));
			helpers.add(new THREE.PlaneHelper(clipPlanes[1], 30, 0x00ff00));
			helpers.add(new THREE.PlaneHelper(clipPlanes[2], 30, 0x0000ff));
			helpers.visible = false;
			scene.add(helpers);
			for (var j = 0; j < clipPlanes.length; j++) {

				clipPlanes[j].constant = 15;

			}


			//outline

			composer = new THREE.EffectComposer(renderer);

			var renderPass = new THREE.RenderPass(scene, camera);
			composer.addPass(renderPass);

			outlinePass = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
			outlinePass.edgeStrength = 2;
			outlinePass.color = 'red';
			outlinePass.edgeGlow = 2;
			outlinePass.edgeThickness = 2;
			outlinePass.pulsePeriod = 1;
			outlinePass.visibleEdgeColor.set('#42d2c1');
			outlinePass.hiddenEdgeColor.set('#a24c00');

			composer.addPass(outlinePass);

			var onLoad = function (texture) {

				outlinePass.patternTexture = texture;
				texture.wrapS = THREE.RepeatWrapping;
				texture.wrapT = THREE.RepeatWrapping;

			};


			effectFXAA = new THREE.ShaderPass(THREE.FXAAShader);
			effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
			effectFXAA.renderToScreen = true;
			composer.addPass(effectFXAA);

			window.addEventListener('resize', onWindowResize, false);

			// window.addEventListener('mousemove', onTouchMove);
			// window.addEventListener('touchmove', onTouchMove);

			function onTouchMove(event) {

				var x, y;

				if (event.changedTouches) {

					x = event.changedTouches[0].pageX;
					y = event.changedTouches[0].pageY;

				} else {

					x = event.clientX;
					y = event.clientY;

				}

				mouse.x = (x / window.innerWidth) * 2 - 1;
				mouse.y = - (y / window.innerHeight) * 2 + 1;

				checkIntersection();

			}

			function addSelectedObject(object) {

				selectedObjects = [];
				selectedObjects.push(object);

			}

			function checkIntersection() {

				raycaster.setFromCamera(mouse, camera);

				var intersects = raycaster.intersectObjects([scene], true);

				if (intersects.length > 0) {


					var selectedObject = intersects[0].object;
					addSelectedObject(selectedObject);
					outlinePass.selectedObjects = selectedObjects;
					console.log(selectedObject.name);
					document.getElementById('promote').style.left = ((mouse.x + 1) / 2 * window.innerWidth).toString() + 'px';
					document.getElementById('promote').style.top = (-(mouse.y - 1) / 2 * window.innerHeight).toString() + 'px';
					document.getElementById('promote').innerText = selectedObject.name;
				} else {

					// outlinePass.selectedObjects = [];
					document.getElementById('promote').innerText = '';

				}

			}


			// window.addEventListener('resize', onWindowResize, false);
			document.addEventListener('pointermove', onTouchMove);

		}

		function onWindowResize() {

			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();

			renderer.setSize(window.innerWidth, window.innerHeight);
			// render();
		}

		function animate() {

			requestAnimationFrame(animate);
			renderer.render(scene, camera);
			composer.render();

		}

		function render() {
			renderer.render(scene, camera);
		}
		function onPointerMove(event) {

			if (selectedObject) {

				selectedObject.material.color.set('#FFF');
				selectedObject = null;

			}

			pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
			pointer.y = - (event.clientY / window.innerHeight) * 2 + 1;

			raycaster.setFromCamera(pointer, camera);

			const intersects = raycaster.intersectObject(group, true);

			if (intersects.length > 0) {

				const res = intersects.filter(function (res) {

					return res && res.object;

				})[0];

				if (res && res.object) {

					selectedObject = res.object;
					selectedObject.material.color.set('#f00');

				}

			}

		}


	</script>

</body>

</html>